package com.luckyframe.project.jmeter.jmeterNode.controller;

import cn.hutool.core.thread.ThreadUtil;
import com.alibaba.fastjson.JSONObject;
import com.luckyframe.common.netty.Result;
import com.luckyframe.common.netty.ServerHandler;
import com.luckyframe.common.netty.jmeter.JmeterNetty;
import com.luckyframe.common.utils.poi.ExcelUtil;
import com.luckyframe.framework.aspectj.lang.annotation.Log;
import com.luckyframe.framework.aspectj.lang.enums.BusinessType;
import com.luckyframe.framework.web.controller.BaseController;
import com.luckyframe.framework.web.domain.AjaxResult;
import com.luckyframe.framework.web.page.TableDataInfo;
import com.luckyframe.project.jmeter.jmeterNode.JmeterNodeDeferredResultHolder;
import com.luckyframe.project.jmeter.jmeterNode.domain.Command;
import com.luckyframe.project.jmeter.jmeterNode.domain.JmeterNode;
import com.luckyframe.project.jmeter.jmeterNode.enums.JmeterNodeStatus;
import com.luckyframe.project.jmeter.jmeterNode.service.IJmeterNodeService;
import org.apache.commons.collections.CollectionUtils;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.context.request.async.DeferredResult;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.ThreadPoolExecutor;

import static java.util.stream.Collectors.toList;

/**
 * 性能测试分布式节点 信息操作处理
 * 
 * @author luckyframe
 * @date 2020-09-11
 */
@Controller
@RequestMapping("/jmeter/jmeterNode")
public class JmeterNodeController extends BaseController
{


	private static final Logger log = LoggerFactory.getLogger(JmeterNodeController.class);


	private String prefix = "jmeter/jmeterNode";
	
	@Autowired
	private IJmeterNodeService jmeterNodeService;

	@Autowired
	private ServerHandler serverHandler;

	@Autowired
	private JmeterNetty nettyServer;

	ThreadPoolExecutor threadPoolExecutor = ThreadUtil.newExecutorByBlockingCoefficient(0.2f);


	@RequiresPermissions("jmeter:jmeterNode:view")
	@GetMapping()
	public String jmeterNode()
	{
	    return prefix + "/jmeterNode";
	}
	
	/**
	 * 查询性能测试分布式节点列表
	 */
	@RequiresPermissions("jmeter:jmeterNode:list")
	@PostMapping("/list")
	@ResponseBody
	public TableDataInfo list(JmeterNode jmeterNode)
	{
		startPage();
        List<JmeterNode> list = jmeterNodeService.selectJmeterNodeList(jmeterNode);
		return getDataTable(list);
	}
	
	
	/**
	 * 导出性能测试分布式节点列表
	 */
	@RequiresPermissions("jmeter:jmeterNode:export")
    @PostMapping("/export")
    @ResponseBody
    public AjaxResult export(JmeterNode jmeterNode)
    {
    	List<JmeterNode> list = jmeterNodeService.selectJmeterNodeList(jmeterNode);
        ExcelUtil<JmeterNode> util = new ExcelUtil<JmeterNode>(JmeterNode.class);
        return util.exportExcel(list, "jmeterNode");
    }


	/**
	 * 新增性能测试分布式节点
	 */
	@GetMapping("/xx")
	@ResponseBody
	public String xx()
	{

		threadPoolExecutor.submit(new Runnable() {
			@Override
			public void run() {
				System.out.println("prefix = " + prefix);
			}
		});
		return prefix + "/add";
	}

	/**
	 * 新增性能测试分布式节点
	 */
	@GetMapping("/yy")
	@ResponseBody
	public String yy()
	{
		return prefix + "/add";
	}

	
	/**
	 * 新增性能测试分布式节点
	 */
	@GetMapping("/add")
	public String add()
	{
	    return prefix + "/add";
	}
	
	/**
	 * 新增保存性能测试分布式节点
	 */
	@RequiresPermissions("jmeter:jmeterNode:add")
	@Log(title = "性能测试分布式节点", businessType = BusinessType.INSERT)
	@PostMapping("/add")
	@ResponseBody
	public AjaxResult addSave(JmeterNode jmeterNode)
	{		
		return toAjax(jmeterNodeService.insertJmeterNode(jmeterNode));
	}

	/**
	 * 修改性能测试分布式节点
	 */
	@GetMapping("/edit/{id}")
	public String edit(@PathVariable("id") Long id, ModelMap mmap)
	{
		JmeterNode jmeterNode = jmeterNodeService.selectJmeterNodeById(id);
		if(jmeterNode!=null){
			//unset
			if(jmeterNode.getCpu()!=null&& jmeterNode.getCpu()==-1){
				jmeterNode.setCpu(null);
			}
			if(jmeterNode.getMemory()!=null&& jmeterNode.getMemory()==-1){
				jmeterNode.setMemory(null);
			}
			if(jmeterNode.getIo()!=null&& jmeterNode.getIo()==-1){
				jmeterNode.setIo(null);
			}
			if(jmeterNode.getDisk()!=null&& jmeterNode.getDisk()==-1){
				jmeterNode.setDisk(null);
			}
			if(jmeterNode.getMaxConcurrency()!=null&& jmeterNode.getMaxConcurrency()==-1){
				jmeterNode.setMaxConcurrency(null);
			}
		}
		mmap.put("jmeterNode", jmeterNode);
	    return prefix + "/edit";
	}
	
	/**
	 * 修改保存性能测试分布式节点
	 */
	@RequiresPermissions("jmeter:jmeterNode:edit")
	@Log(title = "性能测试分布式节点", businessType = BusinessType.UPDATE)
	@PostMapping("/edit")
	@ResponseBody
	public AjaxResult editSave(JmeterNode jmeterNode)
	{

		JmeterNode node = jmeterNodeService.selectJmeterNodeById(jmeterNode.getId());
		if(node==null){
			return AjaxResult.error("记录不存在");
		}

		if(!Objects.equals(jmeterNode.getNodeName(), node.getNodeName())){

			JSONObject msg=new JSONObject();
			msg.put("command", Command.CHANGE_NODE_CONFIG.getCommand());
			msg.put("nodeName",jmeterNode.getNodeName());

			Result result = nettyServer.writeMsg(msg.toJSONString(), jmeterNode.getId());
		}


		return toAjax(jmeterNodeService.updateJmeterNode(jmeterNode));
	}
	
	/**
	 * 删除性能测试分布式节点
	 */
	@RequiresPermissions("jmeter:jmeterNode:remove")
	@Log(title = "性能测试分布式节点", businessType = BusinessType.DELETE)
	@PostMapping( "/remove")
	@ResponseBody
	public AjaxResult remove(String ids)
	{		
		return toAjax(jmeterNodeService.deleteJmeterNodeByIds(ids));
	}


	/**
	 * 根据客户端ID获取状态
	 * @param clientId 客户端ID
	 * @return 返回客户端状态
	 * @author Seagull
	 * @date 2019年8月16日
	 */
	@GetMapping("/getClientStatusByClientId/{clientId}")
	@ResponseBody
	public String getClientStatusByClientId(@PathVariable("clientId") Long clientId)
	{
		JmeterNode client = jmeterNodeService.selectJmeterNodeById(clientId);
		return JSONObject.toJSONString(client);
	}


	/**
	 * 删除性能测试分布式节点
	 */
	@RequiresPermissions("jmeter:jmeterNode:remove")
	@Log(title = "性能测试分布式节点", businessType = BusinessType.DELETE)
	@PostMapping( "/startJmeters")
	@ResponseBody
	public AjaxResult startJmeters(@RequestBody List<Long> ids)
	{
		if(CollectionUtils.isEmpty(ids)){
			return AjaxResult.error("参数错误");
		}

		JSONObject jsonObject=new JSONObject();
		jsonObject.put("command", Command.START.getCommand());

		List<JmeterNode> nodes = ids.stream().map(id -> jmeterNodeService.selectJmeterNodeById(id)).collect(toList());

		//异步启动
		for (JmeterNode node : nodes) {

			nettyServer.writeMsgSync(jsonObject.toJSONString(), node.getId());
			node.setStatus(JmeterNodeStatus.UP.getCode());
			jmeterNodeService.updateJmeterNode(node);
		}

		return AjaxResult.success();
	}



	/**
	 * 删除性能测试分布式节点
	 */
	@GetMapping( "/getNodeStatus")
	@ResponseBody
	public DeferredResult getNodeStatus(@RequestParam("id")Long id )
	{

		Map timeoutData=new HashMap();
		timeoutData.put("type","timeout");

		DeferredResult objectDeferredResult = new DeferredResult(45*1000L,timeoutData);
		objectDeferredResult.onTimeout(()->{
			JmeterNodeDeferredResultHolder.INSTANCE.remoteResult(id,objectDeferredResult);
		});

		JmeterNodeDeferredResultHolder.INSTANCE.bufferDeferredResult(id, objectDeferredResult);
		return objectDeferredResult;
	}



	/**
	 * 删除性能测试分布式节点
	 */
	@PostMapping( "/stopJmeter")
	@ResponseBody
	public AjaxResult stopJmeter(@RequestBody List<Long> ids)
	{
		if(CollectionUtils.isEmpty(ids)){
			return AjaxResult.error("参数错误");
		}

		JSONObject jsonObject=new JSONObject();
		jsonObject.put("command", Command.STOP.getCommand());

		List<JmeterNode> nodes = ids.stream().map(id -> jmeterNodeService.selectJmeterNodeById(id)).collect(toList());

		//异步启动
		for (JmeterNode node : nodes) {

			nettyServer.writeMsgSync(jsonObject.toJSONString(), node.getId());
			node.setStatus(JmeterNodeStatus.JMETER_DOWN.getCode());
			jmeterNodeService.updateJmeterNode(node);
		}

		return AjaxResult.success();
	}



}
